package se.webbzon.boltzmann.editor.factory.propertyframe;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.Collection;
import java.util.Map;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import se.webbzon.boltzmann.editor.component.characterlist.CharacterList;
import se.webbzon.boltzmann.editor.mvc.EditorModel;
import se.webbzon.boltzmann.editor.propertyframe.WorldObjectPropertyFrame;
import se.webbzon.boltzmann.editor.propertyframe.WorldStaticObjectPropertyFrame;
import se.webbzon.boltzmann.game.character.AbstractCharacterTextureSet;
import se.webbzon.boltzmann.game.object.dialogue.DialogueVoice;
import se.webbzon.boltzmann.game.object.npc.FriendlyAI;
import se.webbzon.boltzmann.game.object.spawner.FriendlyNPCSpawner;
import se.webbzon.oschi01.worldobject.WorldObject;

public class FriendlyNPCSpawnerPropertyFrameFactory implements PropertyFrameFactory {
	
	// The map of all available characters
	private final Map<String,AbstractCharacterTextureSet> characterMap;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new property frame factory for hostile npc spawners.  **/
	public FriendlyNPCSpawnerPropertyFrameFactory(Map<String,AbstractCharacterTextureSet> characterMap) {
		this.characterMap = characterMap;
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	@Override public String getWorldObjectName() {
		return FriendlyNPCSpawner.worldObjectName;
	}

	@Override public WorldObjectPropertyFrame makePropertyFrame(EditorModel model,
																WorldObject instance) {
		return new PropertyFrameImpl(model, characterMap, (FriendlyNPCSpawner) instance);
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** An implementation of a property frame. **/
	private static final class PropertyFrameImpl extends WorldStaticObjectPropertyFrame {
		
		// The text fields of this panel
		private final JTextField idInput, keyInput;
		
		// The combo boxes of this panel
		private final JComboBox<FriendlyAI> aiInput;
		private final JComboBox<DialogueVoice> voiceInput;
		
		// The character panel
		private final CharacterList characterPanel;
		
		/*============================================================
		Constructors
		============================================================*/
		
		public PropertyFrameImpl(	EditorModel model, 
									Map<String,AbstractCharacterTextureSet> characterMap,
									FriendlyNPCSpawner instance) {
			super(model, instance);
			
			// Create the character panel
			characterPanel = new CharacterList(	characterMap,
												instance.getCharacterTextureSetName());
			
			// Create npc settings panel
			JPanel npcPanel = new JPanel();
			npcPanel.setLayout(new BoxLayout(npcPanel,BoxLayout.Y_AXIS));
			
			// Add id input panel
			JPanel idPanel = new JPanel();
			idPanel.setLayout(new GridLayout(2,1));
			idPanel.setBorder(BorderFactory.createTitledBorder("Spawner Id:"));
			idPanel.add(new JButton(new RandomizeAction(this)));
			idInput = new JTextField("" + instance.getId());
			idPanel.add(idInput);
			npcPanel.add(idPanel);
			
			// Add key assignment condition input panel
			JPanel keyPanel = new JPanel();
			keyPanel.setLayout(new GridLayout(2,1));
			keyPanel.setBorder(BorderFactory.createTitledBorder("Spawn Key ($ = always spawn):"));
			keyPanel.add(new JLabel("Key:"));
			keyInput = new JTextField("" + instance.getKey());
			keyPanel.add(keyInput);
			npcPanel.add(keyPanel);
						
			// Add ai input panel
			JPanel aiPanel = new JPanel();
			aiPanel.setLayout(new GridLayout(2,1));
			aiPanel.setBorder(BorderFactory.createTitledBorder("AI Settings:"));
			aiInput = new JComboBox<FriendlyAI>(FriendlyAI.values());
			aiInput.setSelectedItem(instance.getAI());
			aiPanel.add(aiInput);
			npcPanel.add(aiPanel);
			
			// Add voice input panel
			JPanel voicePanel = new JPanel();
			voicePanel.setLayout(new GridLayout(2,1));
			voicePanel.setBorder(BorderFactory.createTitledBorder("Voice Settings:"));
			voiceInput = new JComboBox<DialogueVoice>(DialogueVoice.values());
			voiceInput.setSelectedItem(instance.getVoice());
			voicePanel.add(voiceInput);
			npcPanel.add(voicePanel);
			
			// Add panels to property frame
			addPanel(characterPanel.getName(), characterPanel);
			addPanel("NPC Settings", npcPanel);
			initialize();
		}
		
		/*============================================================
		Public Methods
		============================================================*/
		
		@Override public boolean apply(Collection<String> errorMessages) {
			if (super.apply(errorMessages)) try {
				FriendlyNPCSpawner instance = (FriendlyNPCSpawner) getInstance();
				
				long id = Long.parseLong(idInput.getText());
				instance.setId(id);
				instance.setKey(keyInput.getText());
				instance.setCharacterTextureSetName(characterPanel.getTextureSetName());
				instance.setAI((FriendlyAI) aiInput.getSelectedItem());
				instance.setVoice((DialogueVoice) voiceInput.getSelectedItem());
						
				return true;
				
			} catch (NumberFormatException e) {
				errorMessages.add(e.getMessage());
				return false;
				
			} else
				return false;
		}
		
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private static final class RandomizeAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = -7953914687915272175L;
		
		// The property frame associated with this action
		private final PropertyFrameImpl frame;
		
		/*============================================================
		Constructors
		============================================================*/
		
		public RandomizeAction(PropertyFrameImpl frame) {
			this.frame = frame;
			putValue(AbstractAction.NAME, "ID (press to randomize):");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent arg0) {
			long id = new Random().nextLong();
			frame.idInput.setText("" + id);
		}
		
	}

}
